#include "nvhw/sfu.h"

/* These are the bit-exact contents of LUT tables used by Tesla (and Fermi+?)
   Special Function Unit to compute the, well, special functions:

   - rcp (fp32): 1/x
   - rsqrt (fp32): 1/x**2
   - sin and cos (fp32): sin(x) and cos(x), but computed in two stages:

     - presin instruction reduces input modulo tau (aka 2pi), divides by
       tau/4, stores result as a 2.23 fixed-point number (with a few special
       encodings for Inf and NaN).
     - the actual sin/cos instructions compute sin(x/(tau/4)) and
       cos(x/(tau/4)), respectively, with an input format matching
       presin output.  LUT entries for only one quadrant are stored in hw,
       with the remaining 3 (and all of cos) reduced to it via the usual
       trig identities.

   - ex2 (fp32): 2**x, likewise computed in two stages:

     - preex2 converts input to 1.7.23 fixed-point number (in sign-magnitude),
       again with a few encodings reserved for Inf and NaN.
     - actual ex2 instruction operated on inputs in that format

   - lg2 (fp32): lg_2(x)

   What all these functions have in common is that the heavy numerical
   lifting only needs to involve the significand bits without regard to
   the exponent, which can be taken into account later by simple operations:

   - rcp: the hard part is computing values for [1, 2), to get the exponent
     of result just negate the exponent of the input.
   - rsqrt: likewise, but with [1, 4) and new exponent divided by 2.
   - sin and cos: there is no exponent at all once presin is done, only
     quadrants have to be taken into account.  The core computation is
     performed for values in [0, 1).
   - ex2: instead of exponent, there is the integral part, which just goes
     straight to the exponent of the result (after bias).  The core
     computation is performed on values in [0, 1) range.
   - lg2: here in turn, the exponent of the input becomes the integral part
     of the result (with the fractional part coming from computations based
     on the fractional part of the input).  The core computation is performed
     on values in [1, 2).

   So, what remains is computing a function on an interval in a range directly
   corresponding to a full significand range for a single exponent (for rsqrt,
   two ranges are involved: [1, 2) and [2, 4)).  The approach chosen for Tesla
   involves splitting this range into 0x80 (rcp) or 0x40 (non-rcp) slices
   based on the high bits of the significand, storing A=f(x), B=f'(x) and
   C=f''(x) values computed for the start of each slice in a hardware LUT,
   then using these values in polynomial evaluation with the low bits of
   significand to compute approximate final function value.  The algorithm
   is roughly:

     idx = hi(fract)
     r = lo(fract)

     # s0, s1, s2, sr are function-dependent constant shift amounts
     A = tab[idx][0] << s0 // function
     B = tab[idx][1] << s1 // first derivative
     C = tab[idx][2] << s2 // second derivative

     res = A + B * r + C * r * r
     return res >> sr

   The width of table A for each function is 26 bits of precision.  The width
   of tables B and C is, respectively, 16 and 10 bits (for all but sin/cos)
   or 15 and 11 bits (for sin/cos).  The sign of the values is implied by
   the function selected, and is not stored in the LUTs themselves - some
   values thus have an assumed sign bit of 1 (written explicitely in this file
   to ease computations for us).

   Note that the values here are often not true mathematical values - it's in
   fact a rather complex process to compute the LUTs.  They were specifically
   chosen by careful iterative simulation to result in the smallest overall
   error over the whole range of inputs when used in the computation performed
   by the chip, taking into account all roundings and truncations.  You may
   thus see weird stuff like f(x) and f''(x) in tables being a good chunk
   smaller than reality, with f'(x) being larger to compensate.  Don't worry,
   it all works out in the end...
*/


const int32_t sfu_rcp_tab[0x80][3] = {
	/* 1/x, -1/x**2, 1/x**3 (0.26, 0.16, 0.10) */
	{ 0x3fffffe, 0xffff0002, 0x3f5 },
	{ 0x3f80fe0, 0xffff03f6, 0x3dd },
	{ 0x3f03f04, 0xffff07d3, 0x3c6 },
	{ 0x3e88cb3, 0xffff0b99, 0x3b1 },
	{ 0x3e0f83c, 0xffff0f4a, 0x39b },
	{ 0x3d980f6, 0xffff12e5, 0x386 },
	{ 0x3d22636, 0xffff166b, 0x373 },
	{ 0x3cae758, 0xffff19de, 0x35f },
	{ 0x3c3c3c2, 0xffff1d3d, 0x34d },
	{ 0x3bcbadc, 0xffff2089, 0x33b },
	{ 0x3b5cc0f, 0xffff23c3, 0x329 },
	{ 0x3aef6c9, 0xffff26ec, 0x317 },
	{ 0x3a83a83, 0xffff2a03, 0x306 },
	{ 0x3a196b2, 0xffff2d09, 0x2f6 },
	{ 0x39b0ad1, 0xffff2fff, 0x2e6 },
	{ 0x3949660, 0xffff32e5, 0x2d7 },
	{ 0x38e38e3, 0xffff35bc, 0x2c7 },
	{ 0x387f1e0, 0xffff3884, 0x2b8 },
	{ 0x381c0e0, 0xffff3b3d, 0x2aa },
	{ 0x37ba570, 0xffff3de8, 0x29d },
	{ 0x3759f21, 0xffff4085, 0x290 },
	{ 0x36fad87, 0xffff4315, 0x282 },
	{ 0x369d035, 0xffff4597, 0x277 },
	{ 0x36406c8, 0xffff480d, 0x26a },
	{ 0x35e50d7, 0xffff4a77, 0x25d },
	{ 0x358ae04, 0xffff4cd4, 0x252 },
	{ 0x3531dec, 0xffff4f26, 0x246 },
	{ 0x34da034, 0xffff516c, 0x23c },
	{ 0x3483484, 0xffff53a7, 0x231 },
	{ 0x342da7f, 0xffff55d8, 0x225 },
	{ 0x33d91d3, 0xffff57fd, 0x21c },
	{ 0x3385a29, 0xffff5a19, 0x211 },
	{ 0x3333333, 0xffff5c2a, 0x207 },
	{ 0x32e1c9f, 0xffff5e31, 0x1fe },
	{ 0x329161e, 0xffff602f, 0x1f5 },
	{ 0x3241f69, 0xffff6224, 0x1ea },
	{ 0x31f3831, 0xffff640f, 0x1e2 },
	{ 0x31a6032, 0xffff65f1, 0x1da },
	{ 0x3159722, 0xffff67cb, 0x1d1 },
	{ 0x310dcbf, 0xffff699c, 0x1c9 },
	{ 0x30c30c3, 0xffff6b65, 0x1c1 },
	{ 0x30792ef, 0xffff6d26, 0x1b9 },
	{ 0x3030303, 0xffff6edf, 0x1b1 },
	{ 0x2fe80c0, 0xffff7090, 0x1aa },
	{ 0x2fa0be8, 0xffff723a, 0x1a2 },
	{ 0x2f5a441, 0xffff73dc, 0x19c },
	{ 0x2f14990, 0xffff7578, 0x193 },
	{ 0x2ecfb9c, 0xffff770c, 0x18d },
	{ 0x2e8ba2f, 0xffff7899, 0x186 },
	{ 0x2e4850f, 0xffff7a20, 0x17f },
	{ 0x2e05c0a, 0xffff7ba0, 0x179 },
	{ 0x2dc3eee, 0xffff7d19, 0x173 },
	{ 0x2d82d83, 0xffff7e8c, 0x16e },
	{ 0x2d4279a, 0xffff7ffa, 0x166 },
	{ 0x2d02d02, 0xffff8161, 0x161 },
	{ 0x2cc3d8c, 0xffff82c2, 0x15c },
	{ 0x2c8590b, 0xffff841e, 0x155 },
	{ 0x2c47f50, 0xffff8573, 0x151 },
	{ 0x2c0b02c, 0xffff86c4, 0x14b },
	{ 0x2bceb76, 0xffff880f, 0x146 },
	{ 0x2b93105, 0xffff8955, 0x140 },
	{ 0x2b580ae, 0xffff8a95, 0x13c },
	{ 0x2b1da47, 0xffff8bd1, 0x136 },
	{ 0x2ae3da7, 0xffff8d08, 0x131 },
	{ 0x2aaaaaa, 0xffff8e39, 0x12e },
	{ 0x2a7212a, 0xffff8f66, 0x129 },
	{ 0x2a3a0fe, 0xffff908f, 0x123 },
	{ 0x2a02a02, 0xffff91b3, 0x11f },
	{ 0x29cbc15, 0xffff92d2, 0x11b },
	{ 0x2995710, 0xffff93ed, 0x117 },
	{ 0x295fad4, 0xffff9504, 0x112 },
	{ 0x292a73d, 0xffff9616, 0x10f },
	{ 0x28f5c29, 0xffff9725, 0x10a },
	{ 0x28c1979, 0xffff982f, 0x107 },
	{ 0x288df0c, 0xffff9936, 0x102 },
	{ 0x285acc4, 0xffff9a38, 0x100 },
	{ 0x2828283, 0xffff9b37, 0x0fb },
	{ 0x27f6028, 0xffff9c32, 0x0f8 },
	{ 0x27c4598, 0xffff9d2a, 0x0f3 },
	{ 0x27932b4, 0xffff9e1e, 0x0f0 },
	{ 0x2762762, 0xffff9f0e, 0x0ed },
	{ 0x2732386, 0xffff9ffb, 0x0e9 },
	{ 0x2702703, 0xffffa0e4, 0x0e7 },
	{ 0x26d31bf, 0xffffa1cb, 0x0e2 },
	{ 0x26a439f, 0xffffa2ae, 0x0df },
	{ 0x2675c8b, 0xffffa38d, 0x0de },
	{ 0x2647c69, 0xffffa46a, 0x0da },
	{ 0x261a320, 0xffffa544, 0x0d6 },
	{ 0x25ed098, 0xffffa61a, 0x0d4 },
	{ 0x25c04b9, 0xffffa6ee, 0x0d0 },
	{ 0x2593f69, 0xffffa7bf, 0x0cd },
	{ 0x2568096, 0xffffa88c, 0x0cc },
	{ 0x253c825, 0xffffa958, 0x0c7 },
	{ 0x2511602, 0xffffaa20, 0x0c5 },
	{ 0x24e6a17, 0xffffaae5, 0x0c4 },
	{ 0x24bc44e, 0xffffaba8, 0x0c1 },
	{ 0x2492492, 0xffffac69, 0x0bd },
	{ 0x2468acf, 0xffffad27, 0x0ba },
	{ 0x243f6f1, 0xffffade2, 0x0b8 },
	{ 0x24168e1, 0xffffae9b, 0x0b6 },
	{ 0x23ee090, 0xffffaf51, 0x0b4 },
	{ 0x23c5de7, 0xffffb005, 0x0b2 },
	{ 0x239e0d5, 0xffffb0b7, 0x0af },
	{ 0x2376948, 0xffffb166, 0x0ad },
	{ 0x234f72c, 0xffffb213, 0x0ab },
	{ 0x2328a6f, 0xffffb2be, 0x0a9 },
	{ 0x2302302, 0xffffb367, 0x0a6 },
	{ 0x22dc0d1, 0xffffb40d, 0x0a5 },
	{ 0x22b63cc, 0xffffb4b2, 0x0a1 },
	{ 0x2290be2, 0xffffb554, 0x0a0 },
	{ 0x226b902, 0xffffb5f4, 0x09f },
	{ 0x2246b1d, 0xffffb693, 0x09b },
	{ 0x2222222, 0xffffb72f, 0x09a },
	{ 0x21fde02, 0xffffb7c9, 0x099 },
	{ 0x21d9ead, 0xffffb862, 0x096 },
	{ 0x21b6416, 0xffffb8f8, 0x095 },
	{ 0x2192e2a, 0xffffb98d, 0x093 },
	{ 0x216fcdd, 0xffffba20, 0x091 },
	{ 0x214d022, 0xffffbab1, 0x08f },
	{ 0x212a7e6, 0xffffbb40, 0x08f },
	{ 0x2108421, 0xffffbbce, 0x08c },
	{ 0x20e64c2, 0xffffbc5a, 0x08a },
	{ 0x20c49bb, 0xffffbce4, 0x089 },
	{ 0x20a32ff, 0xffffbd6d, 0x087 },
	{ 0x2082082, 0xffffbdf4, 0x085 },
	{ 0x2061237, 0xffffbe79, 0x084 },
	{ 0x204080f, 0xffffbefd, 0x083 },
	{ 0x2020201, 0xffffbf7f, 0x082 },
};

const int32_t sfu_rsqrt_tab[0x80][3] = {
	/* x**-0.5, -x**-1.5, 3/4x**-2.5 (0.26, 0.16, 0.10) */
	{ 0x3fffffd, 0xffff0005, 0x2f2 },
	{ 0x3f817ad, 0xffff05e8, 0x2d5 },
	{ 0x3f05d8f, 0xffff0b91, 0x2ba },
	{ 0x3e8cfe3, 0xffff1105, 0x2a0 },
	{ 0x3e16d08, 0xffff1645, 0x288 },
	{ 0x3da336d, 0xffff1b55, 0x271 },
	{ 0x3d32199, 0xffff2037, 0x25b },
	{ 0x3cc3625, 0xffff24ed, 0x246 },
	{ 0x3c56fbb, 0xffff2979, 0x232 },
	{ 0x3becd12, 0xffff2dde, 0x21f },
	{ 0x3b84cf4, 0xffff321c, 0x20e },
	{ 0x3b1ee3f, 0xffff3637, 0x1fc },
	{ 0x3abafd2, 0xffff3a2f, 0x1ec },
	{ 0x3a590a6, 0xffff3e06, 0x1dc },
	{ 0x39f8fb3, 0xffff41be, 0x1cd },
	{ 0x399ac08, 0xffff4558, 0x1be },
	{ 0x393e4b6, 0xffff48d5, 0x1b1 },
	{ 0x38e38e3, 0xffff4c36, 0x1a4 },
	{ 0x388a7b0, 0xffff4f7e, 0x197 },
	{ 0x3833055, 0xffff52ac, 0x18b },
	{ 0x37dd20a, 0xffff55c2, 0x17f },
	{ 0x3788c11, 0xffff58c1, 0x174 },
	{ 0x3735db5, 0xffff5ba9, 0x16a },
	{ 0x36e4649, 0xffff5e7c, 0x160 },
	{ 0x3694525, 0xffff613b, 0x156 },
	{ 0x36459ab, 0xffff63e6, 0x14c },
	{ 0x35f833b, 0xffff667e, 0x143 },
	{ 0x35ac144, 0xffff6904, 0x13a },
	{ 0x3561336, 0xffff6b79, 0x131 },
	{ 0x3517888, 0xffff6ddc, 0x12a },
	{ 0x34cf0b4, 0xffff7030, 0x122 },
	{ 0x3487b40, 0xffff7273, 0x11b },
	{ 0x34417ae, 0xffff74a8, 0x113 },
	{ 0x33fc587, 0xffff76ce, 0x10c },
	{ 0x33b8456, 0xffff78e6, 0x106 },
	{ 0x33753b4, 0xffff7af1, 0x0ff },
	{ 0x3333333, 0xffff7cef, 0x0f8 },
	{ 0x32f226c, 0xffff7ee0, 0x0f2 },
	{ 0x32b20fe, 0xffff80c5, 0x0ec },
	{ 0x3272e85, 0xffff829e, 0x0e7 },
	{ 0x3234aac, 0xffff846c, 0x0e1 },
	{ 0x31f7512, 0xffff862f, 0x0dc },
	{ 0x31bad67, 0xffff87e7, 0x0d7 },
	{ 0x317f355, 0xffff8995, 0x0d2 },
	{ 0x314468b, 0xffff8b39, 0x0cd },
	{ 0x310a6ba, 0xffff8cd3, 0x0c9 },
	{ 0x30d139a, 0xffff8e64, 0x0c4 },
	{ 0x3098cdc, 0xffff8fed, 0x0bf },
	{ 0x306123e, 0xffff916c, 0x0bb },
	{ 0x302a377, 0xffff92e3, 0x0b7 },
	{ 0x2ff4047, 0xffff9452, 0x0b3 },
	{ 0x2fbe86e, 0xffff95b8, 0x0b0 },
	{ 0x2f89bad, 0xffff9717, 0x0ac },
	{ 0x2f559c5, 0xffff986f, 0x0a8 },
	{ 0x2f2227d, 0xffff99bf, 0x0a5 },
	{ 0x2eef59a, 0xffff9b08, 0x0a2 },
	{ 0x2ebd2e8, 0xffff9c4b, 0x09e },
	{ 0x2e8ba2f, 0xffff9d87, 0x09a },
	{ 0x2e5ab3a, 0xffff9ebc, 0x097 },
	{ 0x2e2a5d5, 0xffff9feb, 0x094 },
	{ 0x2dfa9d0, 0xffffa114, 0x091 },
	{ 0x2dcb6f8, 0xffffa237, 0x08f },
	{ 0x2d9cd26, 0xffffa354, 0x08c },
	{ 0x2d6ec25, 0xffffa46c, 0x089 },
	/* range [1, 2) ends, range [2, 4) starts here */
	/* x**-0.5, -2x**-1.5, 3x**-2.5 (0.26, 0.16, 0.10) */
	{ 0x2d413c9, 0xffff4aff, 0x215 },
	{ 0x2ce7c62, 0xffff4f28, 0x201 },
	{ 0x2c905a6, 0xffff5329, 0x1ed },
	{ 0x2c3ae55, 0xffff5704, 0x1db },
	{ 0x2be754a, 0xffff5aba, 0x1cb },
	{ 0x2b9596c, 0xffff5e4f, 0x1ba },
	{ 0x2b459b1, 0xffff61c2, 0x1ab },
	{ 0x2af7514, 0xffff6517, 0x19c },
	{ 0x2aaaaaa, 0xffff684e, 0x18e },
	{ 0x2a5f987, 0xffff6b6a, 0x180 },
	{ 0x2a160d5, 0xffff6e6a, 0x173 },
	{ 0x29cdfbd, 0xffff7151, 0x167 },
	{ 0x298757d, 0xffff741f, 0x15c },
	{ 0x2942152, 0xffff76d7, 0x150 },
	{ 0x28fe287, 0xffff7978, 0x146 },
	{ 0x28bb875, 0xffff7c03, 0x13c },
	{ 0x287a26b, 0xffff7e7b, 0x132 },
	{ 0x2839fd1, 0xffff80df, 0x129 },
	{ 0x27fb010, 0xffff8330, 0x120 },
	{ 0x27bd291, 0xffff8570, 0x117 },
	{ 0x27806c9, 0xffff879f, 0x10f },
	{ 0x2744c37, 0xffff89bd, 0x107 },
	{ 0x270a257, 0xffff8bcb, 0x100 },
	{ 0x26d08af, 0xffff8dcb, 0x0f8 },
	{ 0x2697ec7, 0xffff8fbc, 0x0f1 },
	{ 0x266042e, 0xffff919f, 0x0eb },
	{ 0x2629879, 0xffff9374, 0x0e5 },
	{ 0x25f3b40, 0xffff953d, 0x0de },
	{ 0x25bec17, 0xffff96f9, 0x0d9 },
	{ 0x258aaa6, 0xffff98aa, 0x0d2 },
	{ 0x2557687, 0xffff9a4f, 0x0cd },
	{ 0x2524f67, 0xffff9be9, 0x0c7 },
	{ 0x24f34e7, 0xffff9d78, 0x0c3 },
	{ 0x24c26bc, 0xffff9efd, 0x0be },
	{ 0x2492493, 0xffffa078, 0x0b9 },
	{ 0x2462e1a, 0xffffa1ea, 0x0b4 },
	{ 0x243430a, 0xffffa352, 0x0b0 },
	{ 0x2406319, 0xffffa4b2, 0x0ab },
	{ 0x23d8e02, 0xffffa609, 0x0a7 },
	{ 0x23ac382, 0xffffa757, 0x0a3 },
	{ 0x2380354, 0xffffa89e, 0x09f },
	{ 0x2354d3d, 0xffffa9dd, 0x09b },
	{ 0x232a0fd, 0xffffab14, 0x098 },
	{ 0x22ffe5d, 0xffffac44, 0x094 },
	{ 0x22d651e, 0xffffad6d, 0x091 },
	{ 0x22ad50e, 0xffffae8f, 0x08e },
	{ 0x2284df7, 0xffffafab, 0x08a },
	{ 0x225cf9f, 0xffffb0c0, 0x088 },
	{ 0x22359db, 0xffffb1cf, 0x085 },
	{ 0x220ec79, 0xffffb2d8, 0x082 },
	{ 0x21e874a, 0xffffb3dc, 0x07e },
	{ 0x21c2a1d, 0xffffb4d9, 0x07c },
	{ 0x219d4c6, 0xffffb5d1, 0x07a },
	{ 0x217871f, 0xffffb6c4, 0x077 },
	{ 0x21540f6, 0xffffb7b2, 0x075 },
	{ 0x213022c, 0xffffb89b, 0x072 },
	{ 0x210ca93, 0xffffb97f, 0x070 },
	{ 0x20e9a08, 0xffffba5e, 0x06e },
	{ 0x20c7067, 0xffffbb39, 0x06b },
	{ 0x20a4d88, 0xffffbc0f, 0x069 },
	{ 0x208314a, 0xffffbce1, 0x067 },
	{ 0x2061b89, 0xffffbdaf, 0x065 },
	{ 0x2040c27, 0xffffbe79, 0x063 },
	{ 0x2020307, 0xffffbf3e, 0x061 },
};

const int32_t sfu_sin_tab[0x40][3] = {
	/* sin(x*tau/4), tau/8*cos(x*tau/4), -tau**2/64*sin(x*tau/4) (0.26, 0.15, 0.11) */
	{ 0x0000000, 0x6489, 0xfffffff2 },
	{ 0x019214e, 0x6482, 0xffffffd0 },
	{ 0x0323ec8, 0x646a, 0xffffffb4 },
	{ 0x04b547c, 0x6444, 0xffffff92 },
	{ 0x0645e94, 0x640d, 0xffffff77 },
	{ 0x07d5934, 0x63c8, 0xffffff55 },
	{ 0x096407a, 0x6373, 0xffffff37 },
	{ 0x0af109c, 0x630e, 0xffffff1b },
	{ 0x0c7c5ba, 0x629b, 0xfffffefa },
	{ 0x0e05c10, 0x6218, 0xfffffedc },
	{ 0x0f8cfc8, 0x6186, 0xfffffebe },
	{ 0x1111d24, 0x60e5, 0xfffffea0 },
	{ 0x129405e, 0x6035, 0xfffffe83 },
	{ 0x14135ca, 0x5f76, 0xfffffe66 },
	{ 0x158f9a2, 0x5ea9, 0xfffffe47 },
	{ 0x170884c, 0x5dcd, 0xfffffe2a },
	{ 0x187de2a, 0x5ce2, 0xfffffe0f },
	{ 0x19ef796, 0x5be9, 0xfffffdf3 },
	{ 0x1b5d0fe, 0x5ae2, 0xfffffdd7 },
	{ 0x1cc66e8, 0x59cd, 0xfffffdbb },
	{ 0x1e2b5d4, 0x58aa, 0xfffffda0 },
	{ 0x1f8ba48, 0x577a, 0xfffffd83 },
	{ 0x20e70ec, 0x563c, 0xfffffd68 },
	{ 0x223d66c, 0x54f0, 0xfffffd50 },
	{ 0x238e760, 0x5398, 0xfffffd35 },
	{ 0x24da0a8, 0x5232, 0xfffffd1e },
	{ 0x261fefc, 0x50c0, 0xfffffd05 },
	{ 0x275ff44, 0x4f42, 0xfffffcea },
	{ 0x2899e5e, 0x4db7, 0xfffffcd4 },
	{ 0x29cd952, 0x4c21, 0xfffffcb9 },
	{ 0x2afad20, 0x4a7e, 0xfffffca5 },
	{ 0x2c216e4, 0x48d0, 0xfffffc8f },
	{ 0x2d413ca, 0x4717, 0xfffffc78 },
	{ 0x2e5a104, 0x4553, 0xfffffc62 },
	{ 0x2f6bbe4, 0x4384, 0xfffffc4e },
	{ 0x30761be, 0x41ab, 0xfffffc39 },
	{ 0x3179008, 0x3fc8, 0xfffffc24 },
	{ 0x327444c, 0x3dda, 0xfffffc14 },
	{ 0x3367c04, 0x3be4, 0xfffffbff },
	{ 0x34534f2, 0x39e4, 0xfffffbed },
	{ 0x3536cc0, 0x37db, 0xfffffbdd },
	{ 0x361214e, 0x35c9, 0xfffffbce },
	{ 0x36e5064, 0x33b0, 0xfffffbbb },
	{ 0x37af812, 0x318e, 0xfffffbad },
	{ 0x3871658, 0x2f65, 0xfffffb9d },
	{ 0x392a960, 0x2d34, 0xfffffb90 },
	{ 0x39daf5c, 0x2afc, 0xfffffb84 },
	{ 0x3a82698, 0x28be, 0xfffffb76 },
	{ 0x3b20d7a, 0x2679, 0xfffffb6c },
	{ 0x3bb6274, 0x242f, 0xfffffb5f },
	{ 0x3c4241c, 0x21df, 0xfffffb54 },
	{ 0x3cc511e, 0x1f89, 0xfffffb4d },
	{ 0x3d3e82c, 0x1d2f, 0xfffffb43 },
	{ 0x3dae822, 0x1ad0, 0xfffffb3c },
	{ 0x3e14fda, 0x186e, 0xfffffb32 },
	{ 0x3e71e78, 0x1607, 0xfffffb2c },
	{ 0x3ec52fc, 0x139d, 0xfffffb26 },
	{ 0x3f0eca0, 0x1130, 0xfffffb21 },
	{ 0x3f4eab2, 0x0ec0, 0xfffffb1e },
	{ 0x3f84c8e, 0x0c4f, 0xfffffb16 },
	{ 0x3fb11b2, 0x09db, 0xfffffb14 },
	{ 0x3fd39ba, 0x0765, 0xfffffb14 },
	{ 0x3fec43c, 0x04ef, 0xfffffb11 },
	{ 0x3ffb10c, 0x0278, 0xfffffb0f },
};

const int32_t sfu_ex2_tab[0x40][3] = {
	/* 2**x/2, ln(2) * 2**x/2, ln(2)**2 ** 2**x (0.26, 0.16, 0.10) */
	{ 0x2000000, 0x58b9, 0x1ee },
	{ 0x2059347, 0x59b0, 0x1f5 },
	{ 0x20b361b, 0x5aaa, 0x1fa },
	{ 0x210e8a2, 0x5ba7, 0x1ff },
	{ 0x216ab0f, 0x5ca6, 0x206 },
	{ 0x21c7d86, 0x5da9, 0x209 },
	{ 0x2226039, 0x5eae, 0x20f },
	{ 0x2285356, 0x5fb6, 0x214 },
	{ 0x22e5709, 0x60c0, 0x21d },
	{ 0x2346b7e, 0x61ce, 0x222 },
	{ 0x23a90e5, 0x62df, 0x227 },
	{ 0x240c772, 0x63f2, 0x22f },
	{ 0x2470f4e, 0x6509, 0x234 },
	{ 0x24d68ad, 0x6623, 0x238 },
	{ 0x253d3c0, 0x673f, 0x241 },
	{ 0x25a50b6, 0x685f, 0x247 },
	{ 0x260dfc2, 0x6982, 0x24d },
	{ 0x2678117, 0x6aa8, 0x254 },
	{ 0x26e34e6, 0x6bd2, 0x258 },
	{ 0x274fb67, 0x6cfe, 0x261 },
	{ 0x27bd4c9, 0x6e2e, 0x267 },
	{ 0x282c145, 0x6f61, 0x26e },
	{ 0x289c10b, 0x7098, 0x273 },
	{ 0x290d456, 0x71d2, 0x279 },
	{ 0x297fb5a, 0x730f, 0x281 },
	{ 0x29f364e, 0x7450, 0x287 },
	{ 0x2a6856a, 0x7594, 0x28f },
	{ 0x2ade8e7, 0x76dc, 0x295 },
	{ 0x2b560fb, 0x7827, 0x29e },
	{ 0x2bcede2, 0x7976, 0x2a5 },
	{ 0x2c48fd7, 0x7ac8, 0x2ae },
	{ 0x2cc4710, 0x7c1f, 0x2b3 },
	{ 0x2d413cc, 0x7d79, 0x2bb },
	{ 0x2dbf648, 0x7ed7, 0x2c1 },
	{ 0x2e3eebe, 0x8038, 0x2cb },
	{ 0x2ebfd6a, 0x819e, 0x2d1 },
	{ 0x2f4228e, 0x8307, 0x2da },
	{ 0x2fc5e67, 0x8474, 0x2e3 },
	{ 0x304b134, 0x85e5, 0x2ec },
	{ 0x30d1b33, 0x875b, 0x2f1 },
	{ 0x3159ca8, 0x88d4, 0x2fb },
	{ 0x31e35d3, 0x8a51, 0x305 },
	{ 0x326e6f7, 0x8bd3, 0x30b },
	{ 0x32fb054, 0x8d59, 0x313 },
	{ 0x3389230, 0x8ee3, 0x31c },
	{ 0x3418ccf, 0x9071, 0x326 },
	{ 0x34aa076, 0x9204, 0x32d },
	{ 0x353cd6a, 0x939b, 0x336 },
	{ 0x35d13f4, 0x9536, 0x341 },
	{ 0x3667457, 0x96d6, 0x34a },
	{ 0x36feede, 0x987b, 0x351 },
	{ 0x37983d3, 0x9a24, 0x35a },
	{ 0x383337d, 0x9bd1, 0x366 },
	{ 0x38cfe27, 0x9d84, 0x36d },
	{ 0x396e41c, 0x9f3b, 0x377 },
	{ 0x3a0e5aa, 0xa0f7, 0x380 },
	{ 0x3ab031d, 0xa2b7, 0x38d },
	{ 0x3b53cc1, 0xa47d, 0x395 },
	{ 0x3bf92e7, 0xa648, 0x39d },
	{ 0x3ca05dd, 0xa817, 0x3aa },
	{ 0x3d495f5, 0xa9ec, 0x3b2 },
	{ 0x3df437f, 0xabc5, 0x3bf },
	{ 0x3ea0ecc, 0xada4, 0x3c9 },
	{ 0x3f4f831, 0xaf88, 0x3d4 },
};

const int32_t sfu_lg2_tab[0x40][3] = {
	/* lg2(x), lg2(e)/x/2, -lg2(e)/x**2 */
	{ 0x0000004, 0xb8a8, 0xfffffd29 },
	{ 0x016e797, 0xb5d1, 0xfffffd3f },
	{ 0x02d75ad, 0xb310, 0xfffffd53 },
	{ 0x043ace7, 0xb064, 0xfffffd67 },
	{ 0x0598fe2, 0xadcc, 0xfffffd7a },
	{ 0x06f210f, 0xab47, 0xfffffd8d },
	{ 0x08462c9, 0xa8d5, 0xfffffd9e },
	{ 0x0995750, 0xa674, 0xfffffdb0 },
	{ 0x0ae00d8, 0xa424, 0xfffffdc0 },
	{ 0x0c26162, 0xa1e4, 0xfffffdd1 },
	{ 0x0d67af5, 0x9fb4, 0xfffffde0 },
	{ 0x0ea4f76, 0x9d93, 0xfffffdee },
	{ 0x0fde0b9, 0x9b81, 0xfffffdfa },
	{ 0x111307c, 0x997c, 0xfffffe08 },
	{ 0x124407c, 0x9784, 0xfffffe15 },
	{ 0x1371251, 0x9599, 0xfffffe21 },
	{ 0x149a786, 0x93ba, 0xfffffe2e },
	{ 0x15c01a8, 0x91e7, 0xfffffe39 },
	{ 0x16e2222, 0x9020, 0xfffffe43 },
	{ 0x1800a59, 0x8e63, 0xfffffe4f },
	{ 0x191bbac, 0x8cb2, 0xfffffe57 },
	{ 0x1a33760, 0x8b0a, 0xfffffe62 },
	{ 0x1b47ebe, 0x896c, 0xfffffe6c },
	{ 0x1c592fb, 0x87d8, 0xfffffe74 },
	{ 0x1d6753f, 0x864c, 0xfffffe7f },
	{ 0x1e726aa, 0x84ca, 0xfffffe87 },
	{ 0x1f7a857, 0x8350, 0xfffffe90 },
	{ 0x207fb52, 0x81df, 0xfffffe97 },
	{ 0x218209f, 0x8076, 0xfffffe9e },
	{ 0x2281942, 0x7f14, 0xfffffea6 },
	{ 0x237e627, 0x7dba, 0xfffffead },
	{ 0x247883b, 0x7c67, 0xfffffeb5 },
	{ 0x257006a, 0x7b1c, 0xfffffeba },
	{ 0x2664f8d, 0x79d7, 0xfffffec1 },
	{ 0x2757682, 0x7898, 0xfffffec9 },
	{ 0x2847614, 0x7761, 0xfffffecd },
	{ 0x2934f0d, 0x762f, 0xfffffed4 },
	{ 0x2a20233, 0x7503, 0xfffffedb },
	{ 0x2b0904a, 0x73de, 0xfffffedf },
	{ 0x2befa00, 0x72be, 0xfffffee5 },
	{ 0x2cd4011, 0x71a3, 0xfffffeec },
	{ 0x2db632e, 0x708e, 0xfffffef1 },
	{ 0x2e963fd, 0x6f7e, 0xfffffef6 },
	{ 0x2f7431d, 0x6e74, 0xfffffefa },
	{ 0x305013a, 0x6d6e, 0xfffffeff },
	{ 0x3129eee, 0x6c6d, 0xffffff03 },
	{ 0x3201cc6, 0x6b71, 0xffffff07 },
	{ 0x32d7b5d, 0x6a79, 0xffffff0c },
	{ 0x33abb41, 0x6985, 0xffffff12 },
	{ 0x347dd00, 0x6896, 0xffffff16 },
	{ 0x354e121, 0x67ac, 0xffffff18 },
	{ 0x361c823, 0x66c5, 0xffffff1d },
	{ 0x36e9293, 0x65e2, 0xffffff21 },
	{ 0x37b40e4, 0x6503, 0xffffff25 },
	{ 0x387d398, 0x6428, 0xffffff28 },
	{ 0x3944b1e, 0x6350, 0xffffff2d },
	{ 0x3a0a7ec, 0x627d, 0xffffff2f },
	{ 0x3acea7a, 0x61ac, 0xffffff34 },
	{ 0x3b91337, 0x60df, 0xffffff37 },
	{ 0x3c52285, 0x6016, 0xffffff39 },
	{ 0x3d118da, 0x5f4f, 0xffffff3d },
	{ 0x3dcf690, 0x5e8c, 0xffffff40 },
	{ 0x3e8bc12, 0x5dcc, 0xffffff43 },
	{ 0x3f469c1, 0x5d0f, 0xffffff46 },
};
